/*******************************************************************************
 * Apache License, Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0)
 * Copyright (c) 2011- kotemaru@kotemaru.org
 ******************************************************************************/
package org.kotemaru.gae.dstool.server;

import java.io.*;
import java.util.*;

import javax.servlet.*;
import javax.servlet.http.*;
import com.google.appengine.api.datastore.*;
import com.google.appengine.api.users.*;
import com.google.appengine.api.oauth.*;
import com.google.apphosting.api.*;

/**
 * DataStore バックアップ サーブレット。
 * <li>データ形式はJSON。
 */
public class DsToolServlet extends HttpServlet  {
	
	
	public void doGet(HttpServletRequest request,HttpServletResponse response)
			throws IOException, ServletException {
		checkAdmin();
		
		String command = request.getParameter("command");
		if (command == null) {
			download(request, response);
		} else if ("remove".equals(command)) {
			remove(request, response);
		} else {
			throw new Error("Unknown command "+command);
		}
	
	}
	/**
	 * Download 処理。
	 * <li>パラメータ<ul>
	 *   <li>kind : DataStoreのEntity kind
	 *   <li>offset : 開始位置。keyのJSON表現。
	 *   <li>limit  : 応答するEntity数の上限。
	 * </ul>
	 * <li>応答データが無いときは 204 レスポンス。
	 * @param request サーブレット要求
	 * @param response サーブレット応答
	 */
	public void download(HttpServletRequest request,HttpServletResponse response)
		throws IOException, ServletException {

		String kind = request.getParameter("kind");
		String offset = request.getParameter("offset");
		int limit = Integer.parseInt(request.getParameter("limit"));

		Key offsetKey = null;
		if (offset != null) {
			offsetKey = EntityParser.parseKey(offset);
		}

		response.setContentType("text/plain; charset=UTF-8");
		Writer writer = response.getWriter();
		EntitySerializer serializer = new EntitySerializer(writer);
		try {
			int count = serializer.serialize(kind, offsetKey, limit);
			if (count == 0) response.setStatus(204);
		} catch (DeadlineExceededException e) {
			// ignore.
		} catch (Exception e) {
			throw new ServletException(e);
		}
	}
	
	public void remove(HttpServletRequest request,HttpServletResponse response)
		throws IOException, ServletException {

		String kind = request.getParameter("kind");
		response.setContentType("text/plain; charset=UTF-8");

		EntityRemover remover = new EntityRemover();
		try {
			int cnt = remover.remove(kind);
			if (cnt == 0) {
				response.setStatus(204);
			}
		} catch (DeadlineExceededException e) {
			// ignore.
		} catch (Exception e) {
			throw new ServletException(e);
		} finally {
			int count = remover.getRemoveCount();
			response.getWriter().write(Integer.toString(count));
			response.getWriter().flush();
		}
	}
	
	
	/**
	 * Upload 処理。
	 * <li>パラメータ<ul>
	 *   <li>kind : DataStoreのEntity kind
	 * </ul>
	 * <li>処理に成功したEntityの数を返す。
	 * @param request サーブレット要求
	 * @param response サーブレット応答
	 */
	public void doPost(HttpServletRequest request,HttpServletResponse response)
		throws IOException, ServletException {
		checkAdmin();
		
		String kind = request.getParameter("kind");
		//String overwrite = request.getParameter("overwrite");
		Reader reader = request.getReader();
		response.setContentType("text/plain; charset=UTF-8");

		EntityParser parser = new EntityParser();
		try {
			parser.parseAndStore(kind, reader);
		} catch (DeadlineExceededException e) {
			// ignore.
		} catch (Exception e) {
			throw new ServletException(e);
		} finally {
			int count = parser.getStoredCount();
			response.getWriter().write(Integer.toString(count));
			response.getWriter().flush();
		}
	}
	
	
	private void checkAdmin() {
		try {
			UserService userService = UserServiceFactory.getUserService();
			if (userService.isUserLoggedIn() && userService.isUserAdmin()) {
				return;
			}
			
			OAuthService oauthService = OAuthServiceFactory.getOAuthService();
			User user = oauthService.getCurrentUser();
			if (user != null && oauthService.isUserAdmin()) {
				return;
			}
		} catch (Exception e) {
			throw new RuntimeException(e);
		}
		throw new RuntimeException("Not admin user.");
	}

}